# 代码功能说明：
# 实现了梯度下降法(gradient descent)的基本算法
# 使用数值梯度计算(numerical_gradient)来近似真实梯度
# 在二维空间演示了梯度下降的优化过程
# 可视化展示了参数更新的路径
# 关键点：
# 学习率(lr)控制每次更新的步长
# step_num控制迭代次数
# 每次迭代都沿负梯度方向更新参数
# 记录参数更新历史以便可视化分析
# 示例函数function_2是一个简单的凸函数，便于演示梯度下降的效果

# 指定文件编码为UTF-8
# coding: utf-8

# 导入NumPy数值计算库
import numpy as np

# 导入matplotlib的pylab绘图模块
import matplotlib.pylab as plt

# 从gradient_2d模块导入数值梯度计算函数
from gradient_2d import numerical_gradient

# 定义梯度下降法函数
def gradient_descent(f, init_x, lr=0.01, step_num=100):
    # 初始化参数x
    x = init_x
    # 创建空列表用于记录x的历史值
    x_history = []

    # 进行指定次数的迭代
    for i in range(step_num):
        # 记录当前x值(使用copy避免引用问题)
        x_history.append(x.copy())

        # 计算当前点的梯度
        grad = numerical_gradient(f, x)
        # 沿负梯度方向更新参数
        x -= lr * grad

    # 返回最终参数和参数更新历史
    return x, np.array(x_history)

# 定义示例函数：f(x0,x1)=x0²+x1²
def function_2(x):
    return x[0]**2 + x[1]**2

# 设置初始点坐标
init_x = np.array([-3.0, 4.0])

# 设置学习率和迭代次数
lr = 0.1
step_num = 20

# 执行梯度下降
x, x_history = gradient_descent(function_2, init_x, lr=lr, step_num=step_num)

# 绘制坐标轴
plt.plot([-5, 5], [0,0], '--b')  # x轴
plt.plot([0,0], [-5, 5], '--b')  # y轴

# 绘制参数更新路径
plt.plot(x_history[:,0], x_history[:,1], 'o')

# 设置坐标轴范围
plt.xlim(-3.5, 3.5)
plt.ylim(-4.5, 4.5)

# 添加坐标轴标签
plt.xlabel("X0")
plt.ylabel("X1")

# 显示图形
plt.show()
